﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraEditors;
using ProgNetComponentsDx.Enums;
using ProgNetComponents;
using ProgNetComponentsDx.Base.Interfaces;

namespace ProgNetComponentsDx.Controls
{
    [Designer(typeof(Design.Designers.PositionControlDesigner))]
    public partial class PositionControl : XtraUserControl, IReadOnlyControl
    {
        [Category("Buttons")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public PositionControlButton BtnUp
        {
            get { return btnUp; }
        }

        [Category("Buttons")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public PositionControlButton BtnDown
        {
            get { return btnDown; }
        }

        [Category("Buttons")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public PositionControlButton BtnTop
        {
            get { return btnTop; }
        }

        [Category("Buttons")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public PositionControlButton BtnBottom
        {
            get { return btnBottom; }
        }

        [Category("Buttons")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public PositionControlButton BtnDelete
        {
            get { return btnDelete; }
        }

        [Category("Buttons")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public PositionControlButton BtnReverse
        {
            get { return btnReverse; }
        }

        #region Events
        [Category(ProgNetComponents.Constants.Categories.ProgNetSettings)]
        public event EventHandler OrderChanged;
        #endregion

        #region Members

        private GridView _GriedView;
        private GridColumn _PositionColumn;
        private bool  _ReadOnly;
        private PaintStyle _PaintStyle;
        private bool _HidePositionColumn = false;
        #endregion

        #region CTOR
        public PositionControl()
        {
            InitializeComponent();
            this.btnBottom.PositionControl = this;
            this.btnDelete.PositionControl = this;
            this.btnDown.PositionControl = this;
            this.btnReverse.PositionControl = this;
            this.btnTop.PositionControl = this;
            this.btnUp.PositionControl = this;
        }
        #endregion

        #region Properties
        [Category(ProgNetComponents.Constants.Categories.ProgNetSettings)]
        public bool ShowDelete
        {
            get { return btnDelete.Visible; }
            set { btnDelete.Visible = value; }
        }

        [Category(ProgNetComponents.Constants.Categories.ProgNetSettings)]
        public bool ShowRevert
        {
            get { return btnReverse.Visible; }
            set { btnReverse.Visible = value; }
        }

        [Category(ProgNetComponents.Constants.Categories.ProgNetSettings)]
        public bool ShowBeginEnd
        {
            get { return btnTop.Visible; }
            set
            {
                btnTop.Visible = value;
                btnBottom.Visible = value;
            }
        }

        [Category(ProgNetComponents.Constants.Categories.ProgNetSettings)]
        public GridView GridView
        {
            get { return _GriedView; }
            set
            {
                DetachEvents(_GriedView);
                _GriedView = value;
                AtachEvents(_GriedView);
                PrepareView();
            }
        }

        [Category(ProgNetComponents.Constants.Categories.ProgNetSettings),
        TypeConverter(typeof(GridColumnConverter))]
        public GridColumn PositionColumn
        {
            get { return _PositionColumn; }
            set { _PositionColumn = value; PrepareView(); }
        }

        [Category(ProgNetComponents.Constants.Categories.ProgNetSettings)]
        public PaintStyle PaintStyle
        {
            get { return _PaintStyle; }
            set
            {
                _PaintStyle = value;
                if (value == PaintStyle.Caption)
                {
                    btnDelete.Image = null;
                    btnDown.Image = null;
                    btnUp.Image = null;
                    btnReverse.Image = null;
                    btnBottom.Image = null;
                    btnTop.Image = null;
                }
                else
                {
                    btnDelete.Image = Properties.Resources.delete24;
                    btnDown.Image = Properties.Resources.down24;
                    btnUp.Image = Properties.Resources.up24;
                    btnReverse.Image = Properties.Resources.refresh24;
                    btnBottom.Image = Properties.Resources.bottom24;
                    btnTop.Image = Properties.Resources.top24;
                    if (value == PaintStyle.Image)
                    {
                        btnDelete.ImageLocation = ImageLocation.MiddleCenter;
                        btnDown.ImageLocation = ImageLocation.MiddleCenter;
                        btnUp.ImageLocation = ImageLocation.MiddleCenter;
                        btnReverse.ImageLocation = ImageLocation.MiddleCenter;
                        btnBottom.ImageLocation = ImageLocation.MiddleCenter;
                        btnTop.ImageLocation = ImageLocation.MiddleCenter;
                    }
                    else
                    {
                        btnDelete.ImageLocation = ImageLocation.MiddleLeft;
                        btnDown.ImageLocation = ImageLocation.MiddleLeft;
                        btnUp.ImageLocation = ImageLocation.MiddleLeft;
                        btnReverse.ImageLocation = ImageLocation.MiddleLeft;
                        btnBottom.ImageLocation = ImageLocation.MiddleLeft;
                        btnTop.ImageLocation = ImageLocation.MiddleLeft;
                    }
                }

            }
        }

        [Category(ProgNetComponents.Constants.Categories.ProgNetSettings)]
        public bool ReadOnly
        {
            get { return _ReadOnly; }
            set
            {
                _ReadOnly = value;
                EnableButtons();
            }
        }

        [Category(ProgNetComponents.Constants.Categories.ProgNetSettings)]
        public bool HidePositionColumn
        {
            get { return _HidePositionColumn; }
            set
            {
                _HidePositionColumn = value;
                PrepareView();
            }
        }
        #endregion

        #region View events
        private void view_InitNewRow(object sender, InitNewRowEventArgs e)
        {
            GridView v = sender as GridView;
            v.SetRowCellValue(e.RowHandle, PositionColumn, GetViewsRowsCount() + 1);
        }
        private void view_RowCountChanged(object sender, EventArgs e)
        {
            if (!ReadOnly)
            {
                UpdatePositions();
                EnableButtons();
            }
        }
        private void view_FocusedRowChanged(object sender, DevExpress.XtraGrid.Views.Base.FocusedRowChangedEventArgs e)
        {
            if (!ReadOnly)
                EnableButtons();
        }
        #endregion

        #region Prepare
        private void PrepareView()
        {
            if (GridView != null && PositionColumn.IsNotNull())
            {
                GridView.OptionsFilter.AllowFilterEditor = false;
                GridView.OptionsCustomization.AllowFilter = false;
                GridView.OptionsCustomization.AllowGroup = false;
                GridView.OptionsView.ShowGroupPanel = false;
                foreach (GridColumn col in GridView.Columns)
                {
                    if (col != PositionColumn)
                    {
                        col.OptionsColumn.AllowSort = DevExpress.Utils.DefaultBoolean.False;
                    }
                    else
                    {
                        col.OptionsColumn.AllowSort = DevExpress.Utils.DefaultBoolean.True;
                        col.SortOrder = DevExpress.Data.ColumnSortOrder.Ascending;
                        col.OptionsColumn.AllowEdit = false;
                        if (HidePositionColumn)
                        {
                            col.OptionsColumn.ShowInCustomizationForm = false;
                            col.Visible = false;
                        }
                    }
                }
                EnableButtons();
            }
        }

        private void AtachEvents(GridView view)
        {
            if (view != null)
            {
                view.FocusedRowChanged += new DevExpress.XtraGrid.Views.Base.FocusedRowChangedEventHandler(view_FocusedRowChanged);
                view.RowCountChanged += new EventHandler(view_RowCountChanged);
                view.InitNewRow += new InitNewRowEventHandler(view_InitNewRow);
            }
        }
        private void DetachEvents(GridView view)
        {
            if (view != null)
            {
                view.FocusedRowChanged -= new DevExpress.XtraGrid.Views.Base.FocusedRowChangedEventHandler(view_FocusedRowChanged);
                view.RowCountChanged -= new EventHandler(view_RowCountChanged);
                view.InitNewRow -= new InitNewRowEventHandler(view_InitNewRow);
            }
        }
        private void EnableButtons()
        {
            if (GridView != null)
            {
                bool isCorrectRow = GridView.FocusedRowHandle != DevExpress.XtraGrid.GridControl.NewItemRowHandle && GridView.FocusedRowHandle >= 0;
                btnDelete.Enabled = !ReadOnly && isCorrectRow;
                btnBottom.Enabled = !ReadOnly && isCorrectRow && GridView.FocusedRowHandle < GetViewsRowsCount() - 1;
                btnDown.Enabled = btnBottom.Enabled;
                btnTop.Enabled = !ReadOnly && GridView.FocusedRowHandle > 0;
                btnUp.Enabled = btnTop.Enabled;
                btnReverse.Enabled = !ReadOnly && GetViewsRowsCount() > 1;
            }
            else
            {
                btnDelete.Enabled =
                btnBottom.Enabled =
                btnDown.Enabled =
                btnTop.Enabled =
                btnUp.Enabled =
                btnReverse.Enabled = false;
            }
        }
        private bool isUpdatePositions = false;
        private void UpdatePositions()
        {
            if (isUpdatePositions)
                return;
            isUpdatePositions = true;

            int max = GetViewsRowsCount();
            bool res = false;
            GridView.BeginDataUpdate();
            try{
                int pos;
            for (int i=0; i < max; i++)
            {
                pos = i + 1;
                if(GridView.GetRowCellValue(i, PositionColumn).AsInt(-1)!=pos){
                    GridView.SetRowCellValue(i, PositionColumn, pos);
                    res = true;
                }
            }
            }finally{
                GridView.EndDataUpdate();
                isUpdatePositions = false;
            }
            if (res)
                OnOrderChanged();
        }
        #endregion

        #region tools
        private int GetViewsRowsCount()
        {
            int count = GridView.RowCount;
            if (GridView.OptionsView.NewItemRowPosition == NewItemRowPosition.Bottom)
                count--;
            return count;
        }
        private void OnOrderChanged()
        {
            if (OrderChanged != null)
                OrderChanged(this, EventArgs.Empty);
        }
        #endregion

        #region Buttons Click
        private void btnUp_Click(object sender, EventArgs e)
        {
            GridView.BeginSort();
            DataRow row = GridView.GetFocusedDataRow();
            DataRow otherRow = GridView.GetDataRow(GridView.FocusedRowHandle - 1);
            int pos = GridView.GetRowCellValue(GridView.FocusedRowHandle, PositionColumn).AsInt();
            int otherPos = GridView.GetRowCellValue(GridView.FocusedRowHandle -1, PositionColumn).AsInt();
            GridView.SetRowCellValue(GridView.FocusedRowHandle, PositionColumn, otherPos);
            GridView.SetRowCellValue(GridView.FocusedRowHandle-1, PositionColumn, pos);
            GridView.EndSort();
            OnOrderChanged();
        }

        private void btnDown_Click(object sender, EventArgs e)
        {
            GridView.BeginSort();
            int pos = GridView.GetRowCellValue(GridView.FocusedRowHandle, PositionColumn).AsInt();
            int otherPos = GridView.GetRowCellValue(GridView.FocusedRowHandle + 1, PositionColumn).AsInt();
            GridView.SetRowCellValue(GridView.FocusedRowHandle, PositionColumn, otherPos);
            GridView.SetRowCellValue(GridView.FocusedRowHandle + 1, PositionColumn, pos);
            GridView.EndSort();
            OnOrderChanged();
        }

        private void btnDelete_Click(object sender, EventArgs e)
        {
            GridView.DeleteRow(GridView.FocusedRowHandle);
        }

        private void btnReverse_Click(object sender, EventArgs e)
        {
            GridView.BeginSort();
            int max = GetViewsRowsCount();
            int pos, otherPos;
            int polowa = max / 2;
            for (int i=0; i < polowa; i++)
            {
                pos = GridView.GetRowCellValue(i, PositionColumn).AsInt();
                otherPos = GridView.GetRowCellValue(max - i - 1, PositionColumn).AsInt();
                GridView.SetRowCellValue(i, PositionColumn, otherPos);
                GridView.SetRowCellValue(max - i - 1, PositionColumn, pos);
            }
            GridView.EndSort();
            OnOrderChanged();
        }

        private void btnTop_Click(object sender, EventArgs e)
        {
            GridView.BeginSort();
            int pos;
            int i = GridView.FocusedRowHandle-1;
            while (i >= 0)
            {
                pos = GridView.GetRowCellValue(i, PositionColumn).AsInt();
                GridView.SetRowCellValue(i, PositionColumn, pos + 1);
                i--;
            }
            GridView.SetRowCellValue(GridView.FocusedRowHandle, PositionColumn, 1);
            GridView.EndSort();
            OnOrderChanged();
        }

        private void btnBottom_Click(object sender, EventArgs e)
        {
            GridView.BeginSort();
            int pos;
            int i = GridView.FocusedRowHandle+1;
            int max = GetViewsRowsCount();

            while (i < max)
            {
                pos = GridView.GetRowCellValue(i, PositionColumn).AsInt();
                GridView.SetRowCellValue(i, PositionColumn, pos-1);
                i++;
            }
            GridView.SetRowCellValue(GridView.FocusedRowHandle, PositionColumn, max);
            GridView.EndSort();
            OnOrderChanged();
        }

        #endregion
    }
    [Designer(typeof(ProgNetComponentsDx.Controls.Design.Designers.PositionControlDesigner.PositionControlButtonDesigner))]
    public class PositionControlButton : SimpleButton
    {
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        internal PositionControl PositionControl
        {
            get;
            set;
        }
    }
    

}
